package com.mvc.security.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import com.mvc.framework.model.Auditable;
import com.mvc.framework.service.BaseService;
import com.mvc.security.model.Department;
import com.mvc.security.model.Menu;

@Service
public class DepartmentManager extends BaseService<Department, Integer> {

	public void save(Department entity) {
		boolean updateChildren = false;
		if(null != entity.getObjectId()){
			updateChildren = true;
		}
		fillFull(entity);
		super.save(entity);
		if (updateChildren) {
			updatePathOfDirectChildren(entity.getObjectId(), entity);
		}
	}

	private void fillFull(Department entity) {
		if (null != entity) {
			if (null != entity.getParentId() && !Department.ROOT.getObjectId().equals(entity.getParentId())) {
				Department parentMenu = getParentDepartment(entity.getParentId());
				if(null!=parentMenu){
					entity.setFullName(parentMenu.getFullName() + Department.PATH_SEPARATOR + entity.getName());
					entity.setLayer(parentMenu.getLayer() + Department.PATH_SEPARATOR + entity.getObjectId());
					return;
				}
			}
			entity.setFullName(Department.PATH_SEPARATOR + entity.getName());
			entity.setLayer(Department.PATH_SEPARATOR + entity.getObjectId());
		}
	}

	public Department getParentDepartment(Integer departmentId) {
		Department department = getDepartmentByDepartmentId(departmentId);
		fillFull(department);
		return department;
	}

	public Department getTopDetartmentByDepartmentId(Integer departmentId){
		Department department = getDepartmentByDepartmentId(departmentId);
		if(null==department){
			return null;
		} else if(Department.ROOT.getObjectId().equals(department.getParentId())){
			return department;
		} else {
			return getTopDetartmentByDepartmentId(department.getParentId());
		}
	}

	protected void updatePathOfDirectChildren(Integer parentId, Department parent) {
		List<Department> needUpdateMenu = getDirectChildren(parentId);
		Session session = getHibernateTemplate().getSessionFactory().openSession();
		for (Department department : needUpdateMenu) {
			department.setFullName(parent.getFullName() + Menu.PATH_SEPARATOR + department.getName());
			department.setLayer(parent.getLayer() + Menu.PATH_SEPARATOR + department.getObjectId());
			updatePathOfDirectChildren(department.getObjectId(), department);
			String hql = "UPDATE " + Department.class.getName() + " SET fullName = ?,LAYER = ? WHERE ID = ?";
			Query query = session.createQuery(hql).setParameter(0, department.getFullName()).setParameter(2, department.getId())
				.setParameter(1, department.getLayer());
			query.executeUpdate();
		}
		session.close();
	}

	public List<Department> getDirectChildren(Integer parentId) {
		if(null!=parentId){
			Department menu = new Department();
			menu.setParentId(parentId);
			menu.setRecStatus(Auditable.REC_STATUS_VALID);
			return getHibernateTemplate().findByExample(menu);
		}
		return new ArrayList<Department>(0);
	}

	public Department getDepartmentByDepartmentId(Integer departmentId) {
		if(null!=departmentId){
			if(Department.ROOT.getObjectId().equals(departmentId)){
				return Department.ROOT;
			}
			Department example = searchByWhere("objectId = " + departmentId + " AND recStatus = " + Auditable.REC_STATUS_VALID);
			return example;
		}
		return null;
	}

	public List<Department> getAll() {
		Department example = new Department();
		example.setRecStatus(Auditable.REC_STATUS_VALID);
		List<Department> result = getHibernateTemplate().findByExample(example);
		result.add(Department.ROOT);
		return result;
	}

	public Department getDepartment(long departmentId,List<Department> departments){
		for(Department department : departments){
			if(departmentId==department.getObjectId()){
				return department;
			}
		}
		return null;
	}
}
